from __future__ import annotations

from dataclasses import dataclass
from datetime import date, datetime, timedelta
from typing import Dict, List

from database import get_timers, TimerRecord


class StatsAnalyzer:
    def __init__(self) -> None:
        self.records: List[tuple[int, datetime]] = self._load_records()

    def _load_records(self) -> List[tuple[int, datetime]]:
        records: List[tuple[int, datetime]] = []
        for rec in get_timers():
            assert isinstance(rec, TimerRecord)
            total_seconds = rec.hours * 3600 + rec.minutes * 60 + rec.seconds
            # created_at 从 DB 取出即为 datetime 对象（naive）
            # 直接用，无需再 parse
            records.append((total_seconds, rec.created_at))
        return records

    def get_weekly_stats(self) -> Dict[str, int]:
        weekly_data: Dict[str, int] = {}
        for seconds, created_dt in self.records:
            # ISO 周: 周一~周日
            year, week, _ = created_dt.isocalendar()
            start_date = datetime.fromisocalendar(year, week, 1).date()
            end_date = datetime.fromisocalendar(year, week, 7).date()
            week_key = f"{year}-W{week:02d}：{start_date}~{end_date}"
            weekly_data[week_key] = weekly_data.get(week_key, 0) + seconds
        return weekly_data

    def get_duration_data(
        self, start_date: datetime | None = None, end_date: datetime | None = None
    ) -> Dict[date, int]:
        if not start_date:
            start_date = datetime.now() - timedelta(days=181)
        if not end_date:
            end_date = datetime.now()

        daily_data: Dict[date, int] = {}
        cur = start_date.date()
        end = end_date.date()
        while cur <= end:
            daily_data[cur] = 0
            cur += timedelta(days=1)

        for seconds, created_dt in self.records:
            d = created_dt.date()
            if start_date.date() <= d <= end:
                daily_data[d] += seconds
        return daily_data

    def get_color_mapping(
        self, start_date: datetime | None = None, end_date: datetime | None = None
    ) -> Dict[date, str]:
        duration_data = self.get_duration_data(start_date, end_date)
        max_seconds = 12 * 3600  # 12 小时上限
        palette = ["#ebedf0", "#9be9a8", "#40c463", "#30a14e", "#216e39"]

        def pick_color(seconds: int) -> str:
            if seconds <= 0:
                return palette[0]
            ratio = float(seconds) / float(max_seconds)
            level = min(4, max(1, int(ratio * 4) + 1))
            return palette[level]

        return {d: pick_color(s) for d, s in duration_data.items()}

    @staticmethod
    def format_duration(seconds: int) -> str:
        hours = seconds // 3600
        minutes = (seconds % 3600) // 60
        return f"{hours}h {minutes}m"
